refs: allow overwrite of empty folders
authorYu Qi Zhang <jzehrarnyg@gmail.com>
Mon, 20 Jun 2016 20:20:58 +0000 (20:20 +0000)
committerAtomic Bot <atomic-devel@projectatomic.io>
Tue, 21 Jun 2016 20:20:15 +0000 (20:20 +0000)
We noticed that once a ref folder is created, there is no existing
command that can remove it. For example, once "foo/bar" is created,
even if the user deletes foo or all the refs under foo, the folder
will persist.

Now when the user attempts to create a ref "foo" either through commit
or refs --create, if a folder "foo" exists but is empty of refs, the
folder is removed and the new ref "foo" is created.

New unit tests in tests-ref.sh verify this functionality.

Closes: #354
Approved by: cgwalters

src/libostree/ostree-repo-refs.c
src/ostree/ot-builtin-commit.c
src/ostree/ot-builtin-refs.c
tests/test-refs.sh

index 29f0333713c161c33e7f563b94b009de82765d26..d9af2256f554d660d9f7f30f62817a893e7e8ad6 100644 (file)
@@ -100,14 +100,51 @@ write_checksum_file_at (OstreeRepo   *self,
   {
     size_t l = strlen (sha256);
     char *bufnl = alloca (l + 2);
+    g_autoptr(GError) temp_error = NULL;
 
     memcpy (bufnl, sha256, l);
     bufnl[l] = '\n';
     bufnl[l+1] = '\0';
 
     if (!_ostree_repo_file_replace_contents (self, dfd, name, (guint8*)bufnl, l + 1,
-                                             cancellable, error))
-      goto out;
+                                             cancellable, &temp_error))
+      {
+        if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY))
+          {
+            g_autoptr(GHashTable) refs = NULL;
+            GHashTableIter hashiter;
+            gpointer hashkey, hashvalue;
+
+            g_clear_error (&temp_error);
+
+            if (!ostree_repo_list_refs (self, name, &refs, cancellable, error))
+              goto out;
+
+            g_hash_table_iter_init (&hashiter, refs);
+
+            while ((g_hash_table_iter_next (&hashiter, &hashkey, &hashvalue)))
+              {
+                if (strcmp (name, (char *)hashkey) != 0)
+                  {
+                    g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                                 "Conflict: %s exists under %s when attempting write", (char*)hashkey, name);
+                    goto out;
+                  }
+              }
+
+            if (!glnx_shutil_rm_rf_at (dfd, name, cancellable, error))
+              goto out;
+
+            if (!_ostree_repo_file_replace_contents (self, dfd, name, (guint8*)bufnl, l + 1,
+                                                     cancellable, error))
+              goto out;
+          }
+        else
+          {
+            g_propagate_error (error, g_steal_pointer (&temp_error));
+            goto out;
+          }
+      }
   }
 
   ret = TRUE;
index 85c4c65d0a51e6035f01414f1b4e3c557a92db2b..ec3ca96073083f48e7318c1fca2d2804a5ed4d04 100644 (file)
@@ -428,7 +428,15 @@ ostree_builtin_commit (int argc, char **argv, GCancellable *cancellable, GError
   else if (!opt_orphan)
     {
       if (!ostree_repo_resolve_rev (repo, opt_branch, TRUE, &parent, error))
-        goto out;
+        {
+          if (g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY))
+            {
+              /* A folder exists with the specified ref name,
+                 * which is handled by _ostree_repo_write_ref */
+              g_clear_error (error);
+            }
+          else goto out;
+        }
     }
 
   if (opt_editor)
index 10647ec639e038dbea208e856c26e32e65dfb7c7..fbdaf1bca57f85a22d575134412f0421576c7c9b 100644 (file)
@@ -74,7 +74,15 @@ static gboolean do_ref (OstreeRepo *repo, const char *refspec_prefix, GCancellab
       g_autofree char *checksum_existing = NULL;
 
       if (!ostree_repo_resolve_rev (repo, opt_create, TRUE, &checksum_existing, error))
-        goto out;
+        {
+          if (g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY))
+            {
+              /* A folder exists with the specified ref name,
+               * which is handled by _ostree_repo_write_ref */
+              g_clear_error (error);
+            }
+          else goto out;
+        }
 
       if (checksum_existing != NULL)
         {
index 3d2290316a47638a2504158e6c24cbfb0ca355dc..310b586fd3f6758ac18ef488c97169d1bd968124 100755 (executable)
@@ -92,8 +92,16 @@ fi
 ${CMD_PREFIX} ostree --repo=repo refs | wc -l > refscount.create1
 assert_file_has_content refscount.create1 "^5$"
 
-${CMD_PREFIX} ostree --repo=repo refs ctest --create ctest-new
+${CMD_PREFIX} ostree --repo=repo refs ctest --create=ctest-new
 ${CMD_PREFIX} ostree --repo=repo refs | wc -l > refscount.create2
 assert_file_has_content refscount.create2 "^6$"
 
+#Check to see if a deleted folder can be re-used as the name of a ref
+${CMD_PREFIX} ostree --repo=repo refs foo/ctest --delete
+${CMD_PREFIX} ostree --repo=repo refs | wc -l > refscount.create3
+assert_file_has_content refscount.create3 "^5$"
+${CMD_PREFIX} ostree --repo=repo refs ctest --create=foo
+${CMD_PREFIX} ostree --repo=repo refs | wc -l > refscount.create4
+assert_file_has_content refscount.create4 "^6$"
+
 echo "ok refs"